﻿using CsharpHttpHelper;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using SelfService.Model.Interface;
using SelfService.Model.Models;
using SelfService.XiaoEn.Models;
using TT;
using WalkingTec.Mvvm.Core;


namespace SelfService.XiaoEn
{
    public class XiaoEnPay : IPaySystem
    {
        private readonly string _url;

        public XiaoEnPay(IOptions<AppSettings> options)
        {
            this._url = options.Value.XiaoEnPayUrl;
        }


        /// <summary>
        /// 获取支付二维码
        /// </summary>
        /// <param name="pay"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        public async Task<ResultDetail<IPay>> GetQrCode(SysPay pay, LoginUserInfo user)
        {
            var request = new QrCodePayValidate();
            request.Body = $"济源市人民医院[{pay.Patient.Name}]{Enum.GetName(typeof(PayUseEnum), pay.Use)}";
            request.OperatorId = user.ITCode;
            request.OperatorName = user.Name;
            request.OutTradeNo = pay.OutOrderNo;
            request.Subject = $"济源市人民医院[{pay.Patient.Name}]{Enum.GetName(typeof(PayUseEnum), pay.Use)}";
            request.TotalFee = (int)(pay.Amount * 100);
            if (pay.PayType.Name == "支付宝")
            {
                request.PaymentMethod = PaymentMethodEnum.Alipay;
            }
            else if (pay.PayType.Name == "微信")
            {
                request.PaymentMethod = PaymentMethodEnum.Wechat;
            }
            else
            {
                return new ResultDetail<IPay>()
                {
                    Code = 1,
                    Message = "不支持的支付类型"
                };
            }
            HttpResult result = default;
            var httpItem = new HttpItem();
            httpItem.URL = $"{_url}/v2/pay/QrCodePay";
            httpItem.Method = "POST";
            httpItem.ContentType = "application/json";
            httpItem.Postdata = JsonConvert.SerializeObject(request);
            try
            {
                await Task.Run(() =>
                {
                    result = new HttpHelper().GetHtml(httpItem);
                });
                if (result.Html.TryJsonParse(out Result<string> response))
                {
                    if (response.Code == 0)
                    {
                        pay.PayUrl = response.Data;
                        return new ResultDetail<IPay>()
                        {
                            Data = pay,
                            Request = httpItem.Postdata,
                            Response = result.Html
                        };
                    }
                    else
                    {
                        return new ResultDetail<IPay>()
                        {
                            Code = 1,
                            Message = response.Message,
                            Request = httpItem.Postdata,
                            Response = result.Html
                        };
                    }
                }
                return new ResultDetail<IPay>()
                {
                    Code = 1,
                    Message = "获取二维码失败, 返回数据解析异常.",
                    Request = httpItem.Postdata,
                    Response = result.Html
                };
            }
            catch (Exception e)
            {
                return new ResultDetail<IPay>()
                {
                    Code = 1,
                    Message = $"获取二维码异常:{JsonConvert.SerializeObject(e)}",
                    Request = httpItem.Postdata
                };
            }
        }

        /// <summary>
        /// 扫码支付
        /// </summary>
        /// <param name="pay"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        public async Task<ResultDetail<IPay>> MicroPay(SysPay pay, LoginUserInfo user)
        {
            var request = new MicroPayValidate();
            request.Body = $"济源市人民医院[{pay.Patient.Name}]{Enum.GetName(typeof(PayUseEnum), pay.Use)}";
            request.OperatorId = user.ITCode;
            request.OperatorName = user.Name;
            request.OutTradeNo = pay.OutOrderNo;
            request.Subject = $"济源市人民医院[{pay.Patient.Name}]{Enum.GetName(typeof(PayUseEnum), pay.Use)}";
            request.TotalFee = (int)(pay.Amount * 100);
            request.AuthCode = pay.AuthCode;
            if (pay.PayType.Name == "支付宝")
            {
                request.PaymentMethod = PaymentMethodEnum.Alipay;
            }
            else if (pay.PayType.Name == "微信")
            {
                request.PaymentMethod = PaymentMethodEnum.Wechat;
            }
            else
            {
                return new ResultDetail<IPay>()
                {
                    Code = 1,
                    Message = "不支持的支付类型"
                };
            }
            HttpResult result = default;
            var httpItem = new HttpItem();
            httpItem.URL = $"{_url}/v2/pay/MicroPay";
            httpItem.Method = "POST";
            httpItem.ContentType = "application/json";
            httpItem.Postdata = JsonConvert.SerializeObject(request);
            try
            {
                await Task.Run(() =>
                {
                    result = new HttpHelper().GetHtml(httpItem);
                });
                if (result.Html.TryJsonParse(out Result<PayResult> response))
                {
                    if (response.Code == 0)
                    {
                        return new ResultDetail<IPay>()
                        {
                            Data = pay,
                            Request = httpItem.Postdata,
                            Response = result.Html
                        };
                    }
                    return new ResultDetail<IPay>()
                    {
                        Code = 1,
                        Message = response.Message,
                        Request = httpItem.Postdata,
                        Response = result.Html
                    };
                }
                return new ResultDetail<IPay>()
                {
                    Code = 1,
                    Message = "扫码支付失败, 返回数据解析异常.",
                    Request = httpItem.Postdata,
                    Response = result.Html
                };
            }
            catch (Exception e)
            {
                return new ResultDetail<IPay>()
                {
                    Code = 1,
                    Message = $"扫码支付异常:{JsonConvert.SerializeObject(e)}",
                    Request = httpItem.Postdata
                };
            }
        }

        /// <summary>
        /// 查询支付结果
        /// </summary>
        /// <param name="pay"></param>
        /// <returns></returns>
        public async Task<ResultDetail<IPay>> GetPayResult(SysPay pay)
        {
            HttpResult result = default;
            var httpItem = new HttpItem();
            httpItem.URL = $"{_url}/v2/pay/{pay.OutOrderNo}";
            try
            {
                await Task.Run(() =>
                {
                    result = new HttpHelper().GetHtml(httpItem);
                });
                if (result.Html.TryJsonParse(out Result<PayResult> response))
                {
                    if (response.Code == 0 && response.Data != null)
                    {
                        switch (response.Data.PayStatus)
                        {
                            case PayOrderStatusEnum.支付成功:
                                pay.PayTime = response.Data.PayTime ?? DateTime.Now;
                                pay.PayStatus = PayStatusEnum.支付成功;
                                pay.SerialsNumber = response.Data.TradeNo;
                                return new ResultDetail<IPay>()
                                {
                                    Data = pay,
                                    Request = httpItem.Postdata,
                                    Response = result.Html
                                };
                            case PayOrderStatusEnum.支付异常:
                            case PayOrderStatusEnum.未支付:
                            case PayOrderStatusEnum.生成失败:
                                pay.PayStatus = PayStatusEnum.支付失败;
                                return new ResultDetail<IPay>()
                                {
                                    Code = 3,
                                    Data = pay,
                                    Request = httpItem.Postdata,
                                    Response = result.Html
                                };
                            case PayOrderStatusEnum.待支付:
                            case PayOrderStatusEnum.生成中:
                                return new ResultDetail<IPay>()
                                {
                                    Code = 2,
                                    Request = httpItem.Postdata,
                                    Response = result.Html
                                };
                            default:
                                return new ResultDetail<IPay>()
                                {
                                    Code = 1,
                                    Message = "未知的支付结果",
                                    Request = httpItem.Postdata,
                                    Response = result.Html
                                };
                        }
                    }
                    else
                    {
                        return new ResultDetail<IPay>()
                        {
                            Code = 1,
                            Message = response.Message,
                            Request = httpItem.Postdata,
                            Response = result.Html
                        };
                    }
                }
                return new ResultDetail<IPay>()
                {
                    Code = 1,
                    Message = "支付失败, 返回数据解析异常.",
                    Request = httpItem.Postdata,
                    Response = result.Html
                };
            }
            catch (Exception e)
            {
                return new ResultDetail<IPay>()
                {
                    Code = 1,
                    Message = $"支付异常:{JsonConvert.SerializeObject(e)}",
                    Request = httpItem.Postdata
                };
            }
        }

        /// <summary>
        /// 退款
        /// </summary>
        /// <param name="pay"></param>
        /// <returns>200=退款成功,1=通讯异常|网络故障|解析数据异常|未知错误,2=退款中,3=退款失败</returns>
        public async Task<ResultDetail<IPay>> Refund(SysPay pay)
        {
            HttpResult result = default;
            var item = new HttpItem();
            item.URL = $"{_url}/v2/refund";
            item.Method = "POST";
            item.ContentType = "application/json";
            item.Postdata = JsonConvert.SerializeObject(new
            {
                OrderId = pay.OutOrderNo,
                RefundTime = DateTime.Now,
                RefundFee = (int)(pay.Amount * 100),
                RefundNo = pay.SerialsNumber,
                Reason = ""
            });
            try
            {
                await Task.Run(() =>
                {
                    result = new HttpHelper().GetHtml(item);
                });
                if (result.Html.TryJsonParse(out Result<RefundResult> response))
                {
                    if (response.Code == 0)
                    {
                        pay.RefundId = response.Data.Id;
                        pay.RefundNo = response.Data.RefundNo;
                        if (response.Data.Status == RefundStatusEnum.退款成功)
                        {
                            return new ResultDetail<IPay>()
                            {
                                Code = 200,
                                Data = pay,
                                Message = "退款成功",
                                Request = item.Postdata,
                                Response = result.Html,
                            };
                        }else if (response.Data.Status == RefundStatusEnum.退款失败)
                        {
                            return new ResultDetail<IPay>()
                            {
                                Code = 3,
                                Data = pay,
                                Message = "退款失败",
                                Request = item.Postdata,
                                Response = result.Html,
                            };
                        }
                        else
                        {
                            return new ResultDetail<IPay>()
                            {
                                Code = 2,
                                Data = pay,
                                Message = "退款中",
                                Request = item.Postdata,
                                Response = result.Html,
                            };
                        }
                    }
                    else
                    {
                        return new ResultDetail<IPay>()
                        {
                            Code = 1,
                            Message = response.Message,
                            Request = item.Postdata,
                            Response = result.Html,
                        };
                    }
                }
                return new ResultDetail<IPay>()
                {
                    Code = 1,
                    Message = "退款失败, 返回数据解析异常.",
                    Request = item.Postdata,
                    Response = result.Html,
                };
            }
            catch (Exception e)
            {
                return new ResultDetail<IPay>()
                {
                    Code = 1,
                    Message = $"退款异常:{JsonConvert.SerializeObject(e)}",
                    Request = item.Postdata
                };
            }
        }
        
        
        /// <summary>
        /// 退款
        /// </summary>
        /// <param name="pay"></param>
        /// <returns>200=退款成功,1=通讯异常|网络故障|解析数据异常|未知错误,2=退款中,3=退款失败</returns>
        public async Task<ResultDetail<IPay>> CheckRefund(SysPay pay)
        {
            HttpResult result = default;
            var item = new HttpItem();
            item.URL = $"{_url}/v2/refund/info";
            item.Method = "POST";
            item.ContentType = "application/json";
            item.Postdata = JsonConvert.SerializeObject(new
            {
                OrderId = pay.OutOrderNo,
                Id = pay.RefundId
            });
            try
            {
                await Task.Run(() =>
                {
                    result = new HttpHelper().GetHtml(item);
                });
                if (result.Html.TryJsonParse(out Result<RefundResult> response))
                {
                    if (response.Code == 0)
                    {
                        pay.RefundId = response.Data.Id;
                        pay.RefundNo = response.Data.RefundNo;
                        if (response.Data.Status == RefundStatusEnum.退款成功)
                        {
                            return new ResultDetail<IPay>()
                            {
                                Code = 200,
                                Data = pay,
                                Message = "退款成功",
                                Request = item.Postdata,
                                Response = result.Html,
                            };
                        }else if (response.Data.Status == RefundStatusEnum.退款失败)
                        {
                            return new ResultDetail<IPay>()
                            {
                                Code = 3,
                                Data = pay,
                                Message = "退款失败",
                                Request = item.Postdata,
                                Response = result.Html,
                            };
                        }
                        else
                        {
                            return new ResultDetail<IPay>()
                            {
                                Code = 2,
                                Data = pay,
                                Message = "退款中",
                                Request = item.Postdata,
                                Response = result.Html,
                            };
                        }
                    }
                    else
                    {
                        return new ResultDetail<IPay>()
                        {
                            Code = 1,
                            Message = response.Message,
                            Request = item.Postdata,
                            Response = result.Html,
                        };
                    }
                }
                return new ResultDetail<IPay>()
                {
                    Code = 1,
                    Message = "查询退款失败, 返回数据解析异常.",
                    Request = item.Postdata,
                    Response = result.Html,
                };
            }
            catch (Exception e)
            {
                return new ResultDetail<IPay>()
                {
                    Code = 1,
                    Message = $"查询退款异常:{JsonConvert.SerializeObject(e)}",
                    Request = item.Postdata
                };
            }
        }
        
        
        private class PayResult
        {
            /// <summary>
            /// 0=订单创建中,1=订单创建失败,2=待支付,3=未支付,4=支付成功,5=支付异常
            /// </summary>
            public PayOrderStatusEnum PayStatus { get; set; }

            public DateTime? PayTime { get; set; }

            public string TradeNo { get; set; }
        }

        /// <summary>
        /// 退款返回数据
        /// </summary>
        private class RefundResult
        {
            public string Id { get; set; }
            public string RefundNo { get; set; }
            public RefundStatusEnum Status { get; set; }
        }
        
        private enum PayOrderStatusEnum
        {
            生成中,
            生成失败,
            待支付,
            未支付,
            支付成功,
            支付异常
        }

        /// <summary>
        /// status:0=待退款,10=退款中,20=退款成功,30=退款失败
        /// </summary>
        private enum RefundStatusEnum
        {
            待退款 = 0,
            退款中 = 10,
            退款成功 = 20,
            退款失败 = 30
        }
    }
}